/*
 * This file is part of b.AMP.
 *
 * b.AMP is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * b.AMP is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with b.AMP.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <boost/test/unit_test.hpp>
#include <bamp/basic_message.hpp>

BOOST_AUTO_TEST_CASE( basic_message_ctor )
{
    const std::string name = "MessageName";
    bamp::BasicMessage bm1;
    bamp::BasicMessage bm2(name);

    BOOST_CHECK_EQUAL(bm1.getName(), std::string(""));
    BOOST_CHECK_EQUAL(bm1.getArgc(), 0);
    BOOST_CHECK_EQUAL(bm2.getName(), name);
    BOOST_CHECK_EQUAL(bm2.getArgc(), 0);
}

BOOST_AUTO_TEST_CASE( basic_message_copy )
{
    const std::string name = "MessageName";

    // Empty message copy
    bamp::BasicMessage bm1;
    bamp::BasicMessage bm2(bm1);
    BOOST_CHECK_EQUAL(bm2.getName(), std::string(""));
    
    // Name copy
    bm1.setName(name);
    bamp::BasicMessage bm3(bm1);
    BOOST_CHECK_EQUAL(bm3.getName(), name);

    // Argument copy
    std::string argname = "FirstArg";
    bamp::Value argvalue = std::string("FirstValue");
    bm3.setArg(argname, argvalue);
    bamp::BasicMessage bm4(bm3);
    BOOST_CHECK_EQUAL(bm4.getArgc(), 1);
    BOOST_CHECK_EQUAL(bm4.getArg(0), argvalue);
    BOOST_CHECK_EQUAL(bm4.getArg(0), bm3.getArg(0));
    BOOST_CHECK_EQUAL(bm4.getArgByName(argname), argvalue);
    BOOST_CHECK_EQUAL(bm4.getArgByName(argname), bm3.getArgByName(argname));
    BOOST_CHECK_EQUAL(bm4.getArgName(0), argname);
    BOOST_CHECK_EQUAL(bm4.getArgName(0), bm3.getArgName(0));

    // operator=
    bamp::BasicMessage bm5("WrongName");
    bm5 = bm4;
    BOOST_CHECK_EQUAL(bm5.getArgc(), 1);
    BOOST_CHECK_EQUAL(bm5.getArg(0), argvalue);
    BOOST_CHECK_EQUAL(bm5.getArg(0), bm4.getArg(0));
    BOOST_CHECK_EQUAL(bm5.getArgByName(argname), argvalue);
    BOOST_CHECK_EQUAL(bm5.getArgByName(argname), bm4.getArgByName(argname));
    BOOST_CHECK_EQUAL(bm5.getArgName(0), argname);
    BOOST_CHECK_EQUAL(bm5.getArgName(0), bm4.getArgName(0));
}


BOOST_AUTO_TEST_CASE( basic_message_name )
{
    // Basic get/set test
    const std::string name = "MessageName";
    bamp::BasicMessage bm1(name);
    bamp::BasicMessage bm2;
    bm2.setName(name);
    BOOST_CHECK_EQUAL(bm1.getName(), bm2.getName());
    BOOST_CHECK_EQUAL(bm2.getName(), name);
}


BOOST_AUTO_TEST_CASE( basic_message_args )
{
    // Basic get/set arg
    bamp::BasicMessage bm1;
    std::string argName = "ArgName";
    std::string argValue = "ArgValue";
    bm1.setArg(argName, argValue);
    BOOST_CHECK_EQUAL(bm1.getArgByName(argName), argValue);
    BOOST_CHECK_EQUAL(bm1.getArgName(0), argName);
}


BOOST_AUTO_TEST_CASE( basic_message_ptr )
{
    bamp::MessagePtr ptr1(new bamp::BasicMessage());
    BOOST_CHECK_EQUAL(ptr1.cptr()->__refs, 1);

    bamp::MessagePtr ptr2 = ptr1;
    BOOST_CHECK_EQUAL(ptr1.cptr()->__refs, 2);
    BOOST_CHECK_EQUAL(ptr1.cptr(), ptr2.cptr());

    {
        bamp::MessagePtr ptr3(ptr1);
        BOOST_CHECK_EQUAL(ptr1.cptr()->__refs, 3);
        BOOST_CHECK_EQUAL(ptr1.cptr(), ptr3.cptr());
    }
    BOOST_CHECK_EQUAL(ptr1.cptr()->__refs, 2);

    const std::string name = "MessageName";
    ptr1.setName(name);
    BOOST_CHECK_EQUAL(ptr1.getName(), name);

    bamp::MessagePtr ptr4 = ptr1.clone();
    BOOST_CHECK_EQUAL(ptr4.getName(), name);
    BOOST_CHECK_EQUAL(ptr4.cptr()->__refs, 1);

    const std::string name2 = "BasicMessage";
    bamp::BasicMessage bm1(name2);
    std::string argName = "ArgName";
    std::string argValue = "ArgValue";
    bm1.setArg(argName, argValue);

    bamp::Message* msg1 = bm1.clone();
    BOOST_CHECK_EQUAL(msg1->getName(), name2);
    BOOST_CHECK_EQUAL(msg1->getArgc(), 1);
    BOOST_CHECK_EQUAL(msg1->getArg(0), argValue);
    
    bamp::MessagePtr ptr5 = bm1.clone();
    BOOST_CHECK_EQUAL(ptr5.getName(), name2);
    BOOST_CHECK_EQUAL(ptr5.getArgc(), 1);
    BOOST_CHECK_EQUAL(ptr5.getArg(0), argValue);
}
